#include "thread_pool.h"
#include "linked_list.h"
#include "config.h"
#include "user.h"

#define  EPOLL_ARR_SIZE 100
int exitPipe[2];
ListNode* userList = NULL;

void sigHandler(int num){
    printf("\n sig is coming.\n");
    int one=1; //激活管道，往管道里面写1
    write(exitPipe[1],&one,sizeof(one));
}
//父进程守护 + 子进程处理业务 + epoll 事件驱动 + 线程池并发
int main(int argc,char** argv)
{
    //命令行参数读取配置文件
    ARGS_CHECK(argc,2);
    //创建退出匿名管道
    pipe(exitPipe);
    

    //创建子进程
    pid_t pid =fork();

    if(pid>0){  //大于0是父进程
        close(exitPipe[0]);//父进程关闭读端
        signal(SIGUSR1,sigHandler);
        wait(NULL); //等待子进程退出，回收资源
        close(exitPipe[1]);
        printf("\nparent process exit\n");
        exit(0); //父进程退出
    }
    //以下是子进程
    
    close(exitPipe[1]);  //子进程关闭写端

    //初始化哈希表
    HashTable ht;
    initHashTable(&ht);
    //读取配置文件
    readConfig(argv[1],&ht);




    //创建线程池
    threadpool_t threadpool;
    memset(&threadpool,0,sizeof(threadpool));
    //初始化线程
    threadpoolInit(&threadpool,atoi((const char*)find(&ht,THREAD_NUM)));
    //启动线程池

    threadpoolStart(&threadpool);

    //创建监听套接字
    int listenfd = tcpInit((char*)find(&ht,IP),(char*)find(&ht,PORT));
    
    //创建epoll实例
    int epfd = epoll_create1(0);
    ERROR_CHECK(epfd,-1,"epoll_create1");

    //对listenfd进行监听
    addEpollReadfd(epfd,listenfd);
    addEpollReadfd(epfd,exitPipe[0]);  //监听退出的管道

    struct epoll_event* pEventArr = (struct epoll_event*)
        calloc(EPOLL_ARR_SIZE,sizeof(struct epoll_event));
    while(1){
        int nready = epoll_wait(epfd,pEventArr,EPOLL_ARR_SIZE,-1);
        if(nready==-1 && errno ==EINTR){
            continue;
        }else if(nready==-1){
            ERROR_CHECK(nready,-1,"epoll_wait");
        }else{
            for(int i=0;i<nready;++i){
                int fd =pEventArr[i].data.fd;
                if(fd==listenfd){
                    int peerfd = accept(listenfd,NULL,NULL);
                    printf("\n conn %d has conneted.\n",peerfd);

                    //将新连接添加到epoll监听红黑树上
                    addEpollReadfd(epfd,peerfd);
                    //添加用户节点
                    user_info_t* user = (user_info_t*)calloc(1,sizeof(user_info_t));
                    user->sockfd =peerfd;
                    appendNode(&userList,user);

                }else if(fd==exitPipe[0]){
                    //线程池退出
                    int howmany=0;
                    //对管道处理
                    read(exitPipe[0],&howmany,sizeof(howmany));
                    //主线程通知所有的子线程退出
                    threadpoolStop(&threadpool);
                    //子进程退出前，回收资源
                    threadpoolDestroy(&threadpool);
                    close(listenfd);
                    close(epfd);
                    close(exitPipe[0]);
                    printf("\n child process exit.\n");
                    destroyHashTable(&ht);
                    exit(0);
                }else{
                    handleMessage(fd,epfd,&threadpool.que);
                }
            }
        }
    }


    



    return 0;
}

